package com.snack.page;


import java.sql.SQLException;

/**
 * 分页查询。<p>
 * 根据查询语句和页码查询出当页数据。
 * <p>
 * Copyright: Copyright (c) Feb 6, 2009 3:39:21 PM
 * <p>
 * Company: 北京宽连十方数字技术有限公司
 * <p>
 * Author: chengyao
 * <p>
 * Version: 1.0
 * <p>
 */
public abstract class AbstractPagedStatement<T> {
    
    /** 每页允许的最大记录数 */
    public final static int MAX_PAGESIZE = Page.MAX_PAGESIZE;

    /** 查询总记录数的SQL */
    protected String countSql;
    
    /** 查询SQL */
    protected String querySql;

    /** 当前显示页 */
    protected int currentPage;
    
    /** 每页记录数 */
    protected int pageSize;
    
    /** 当前显示页从记录集开始的位置 */
    protected int startIndex;
    
    /** 总记录数 */
    protected int totalCount;
    
    /** 显示当前页是否需要偏移 */
    protected boolean hasOffset;
    
    /**
     * 构造一查询出所有数据的PageStatement
     * 
     * @param sql 查询SQL
     */
    public AbstractPagedStatement(String sql) {
        this(sql, 1, Page.DEFAULT_PAGESIZE);
    }

    /**
     * 构造一查询出当页数据的PageStatement
     * 
     * @param sql query sql
     * @param currentPage 页码
     */
    public AbstractPagedStatement(String sql, int currentPage) {
        this(sql, currentPage, Page.DEFAULT_PAGESIZE);
    }

    /**
     * 构造一查询出当页数据的PageStatement，并指定每页显示记录条数
     * 
     * @param sql query sql
     * @param currentPage 页码
     * @param pageSize 每页容量
     */
    public AbstractPagedStatement(String sql, int currentPage, int pageSize) {
        this.currentPage = currentPage;
        this.pageSize = pageSize;
        this.startIndex = Page.getStartOfAnyPage(currentPage, pageSize);
        this.hasOffset = currentPage > 1; 
        this.countSql = getCountingSql(sql);
        this.querySql = getPagingSql(sql);
    }

    /**
     * 执行查询
     * @param type 预定义的查询类型，会返回不同类型分页对象
     * @return 分页对象
     * @throws SQLException if a database access error occurs
     */
    protected abstract Page<T> executeQuery(int type) throws SQLException;

    /**
     * 获取查询记录数的sql语句
     * 
     * @param sql 原查询语句
     * @return 查询记录数的SQL
     */
    protected String getCountingSql(String sql) {
        return "select count(1) from ( " + sql + ")t";
    }
    
    
    /**
     * 生成查询一页数据的sql语句，这里是针对ORACLE的实现
     * 
     * @param sql 原查询语句
     * @return 查询当前页的SQL
     */
    protected String getPagingSql(String sql) {
        StringBuffer ret = new StringBuffer(sql.length()+100);
        ret.append("select * from ( ");
        ret.append(sql);
        if (this.hasOffset) {
            ret.append(" )t limit ?,?");
        }
        else {
            ret.append(" )t limit ?");
        }
        return ret.toString();
    }

}
